/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * panelCoordPlane.java
 *
 * Created on 31/01/2010, 06:22:39 PM
 */

package Util;

import java.awt.*;
import java.awt.Color;
import java.util.Vector;

import java.awt.geom.AffineTransform;

/**
 *
 * @author alejo
 */
public class panelCoordPlane extends javax.swing.JPanel {

    
    public static final int POLAR_COORD = 0;
    public static final int CARTESIAN_COORD = 1;
    private int planeType;
    private int div1;
    private int div2;

    //how many pixels represents a meter
    private int m2px;

    //static and dynamic elements to be drawn
    private Vector staticElems;
    private Vector dynElems;

    private Sector[] sectors;

    //drawTable specifies if the rectangle containing vector names should be drawn
    private boolean isTableEnabled = true;
    //defines wheter the graphic should rotate
    private boolean isRotating = false;
    //how many should the drawing rotate
    private float rotAngle;



    /** Creates new form panelCoordPlane */
    public panelCoordPlane(int type, int divX, int divY) {
        initComponents();
        this.planeType = type;
        this.div1 = divX;
        this.div2 = divY;

        sectors = new Sector[div2];

        staticElems = new Vector(0);
        dynElems = new Vector(0);

        calculateSectors();
    }

    public void rotate(float angle)
    {
        this.rotAngle = angle;
        this.isRotating = true;
    }
    public void addStaticElement(String name, int type, float radius, float x,float y, Color color)
    {
        Element e = new Element(name, type, radius, x, y, color);

        staticElems.add(e);

    }

    public void addDynElement(String name, int type, float radius, float x,float y, Color color)
    {
        Element e = new Element(name, type, radius, x, y, color);

        dynElems.add(e);

    }

    public void setSectorColor(int index,Color color)
    {
        this.sectors[index].color = color;
    }

    public void setOccupiedSector(int index)
    {
        if(index==0)
            index = div2-1;
        else
            index--;
        this.sectors[index].setOccupied();
    }

    public void setFreeSector(int index)
    {
        if(index==0)
            index = div2-1;
        else
            index--;

        this.sectors[index].setFree();
    }

    public void resetDynElements()
    {
        dynElems.clear();
    }

    public void resetStaticElements()
    {
        staticElems.clear();
    }

    public void drawTable(boolean isTableEnabled)
    {
        this.isTableEnabled = isTableEnabled;
    }

    private void calculateSectors()
    {
        double angleStep = (2*Math.PI/div2);

        int[] xPoints = new int[div2+1];
        int[] yPoints = new int[div2+1];

        xPoints[0] = 0;
        yPoints[0] = 0;

        int x = 0;
        int y = 0;
        for(int i=1;i<=div2;i++)
        {
            x = (int)(Math.cos(angleStep*i)*1000);
            y = -(int)(Math.sin(angleStep*i)*1000);


            xPoints[i] = x;
            yPoints[i] = y;

            //define sectors
            if(i>1)
            {
                int[] xp = {xPoints[0],xPoints[i-1],xPoints[i]};
                int[] yp = {yPoints[0],yPoints[i-1],yPoints[i]};

                sectors[i-2] = new Sector( xp, yp, Color.WHITE,i-2);
            }
        }
        int[] xp = {xPoints[0],xPoints[1],xPoints[div2]};
        int[] yp = {yPoints[0],yPoints[1],yPoints[div2]};
        sectors[sectors.length-1] = new Sector( xp, yp, Color.WHITE,div2-1);

    }

    @Override public void paint(Graphics g)
    {
        super.paint(g);
        Graphics2D g2d = null;
        g2d = (Graphics2D)g;



        int w = this.getWidth();
        int h = this.getHeight();

        if(isRotating)
        {
            AffineTransform at = new AffineTransform();
            Vector2d centerPos = new Vector2d(w/2,h/2,Vector2d.MODE_XY);
            Vector2d newPos = new Vector2d(centerPos);
            newPos = newPos.rotate(rotAngle);
            
            Vector2d translation = centerPos.sub(newPos);

            //int trans = (int)(Math.sqrt((w/2)*(w/2)+(h/2)*(h/2))-h/2);
            //at.translate (w/2,-trans);//-(int)(Math.sqrt(w^2-(h/2)^2)));


            at.translate (translation.x,translation.y);
            at.rotate(rotAngle);
            g2d.setTransform(at);
            //this.isRotating = false;
        }


        //calculate the unit meters to pixels, according to the size of the panel
        m2px = Math.min(w, h)/4;

        //paint lines
        switch(planeType)
        {
            case POLAR_COORD:

                //in this case, div1 refers to how many sections should the maxSize
                //be divided.
                //for magnitude. div2 refers to how many divisions are
                //to be appeared as angle sections

                double angleStep = (2*Math.PI/div2);
                
                //draw sectors first
                for(int i=0;i<div2;i++)
                {
                    Sector s = sectors[i];
                    s.draw(g, w/2, h/2);
                }

                // now, draw plane origins
                g.setColor(new Color(219,219,219));
                
                g.drawLine(w/2, 0, w/2, h);
                g.drawLine(0, h/2, w, h/2);

                //draw circles for magnitude
                g.setColor(new Color(219,219,219));

                for(int i=0;i<Math.max(w/(div1),h/(div1));i++)
                {
                    g.drawOval(w/2-m2px/div1*i, h/2-m2px/div1*i, m2px/div1*i*2, m2px/div1*i*2);

                }

                //draw lines for angles
                for(int i=1;i<=div2;i++)
                {
                    int x = (int)(Math.cos(angleStep*i)*1000);
                    int y = (int)(Math.sin(angleStep*i)*1000);
                    g.setColor(new Color(219,219,219));
                    g.drawLine(w/2, h/2, w/2+x, h/2+y);
                }



            break;
            case CARTESIAN_COORD:
                for(int i=0;i<Math.max(w/div1,h/div2);i++)
                {
                    if(i==0)
                        g.setColor(Color.GRAY);
                    else
                        g.setColor(new Color(219,219,219));

                    //lineas verticales
                    g.drawLine(w/2-div1*i, 0, w/2-div1*i, h);
                    g.drawLine(w/2+div1*i, 0, w/2+div1*i, h);
                    //lineas horizontales
                       if(i<h/18)
                    {
                        g.drawLine(0, h/2-div2*i, w, h/2-div2*i);
                        g.drawLine(0, h/2+div2*i, w, h/2+div2*i);
                    }

                }
                //paint circle of radius 1
                g.drawOval(w/2-m2px, h/2-m2px, m2px*2, m2px*2);

            break;
        }

        //now draw dynamic elements (Vectors or circles)
        if(!dynElems.isEmpty())
        {

            //draw rectangle for names
            if(isTableEnabled)
            {
                ((Graphics2D)g).setStroke(new BasicStroke(1.0f));
                g.setColor(Color.BLACK);
                g.drawRect(w-120, h*2/10,120, (dynElems.size()+1)*18);
                g2d.setColor(Color.WHITE);
                g2d.fillRect(w-119, h*2/10+1,119, (dynElems.size()+1)*18-1);
            }
            for(int i= 0; i<dynElems.size();i++)
            {
                Element e = (Element)dynElems.get(i);
                g.setColor(e.color);
                
                //calculate position
                int x = (int)(e.x*m2px);
                int y = -(int)(e.y*m2px);
                

                switch(e.type)
                {
                    case Element.IS_CIRCLE:
                        //draw filled circles
                        g2d.fillOval((int)(w/2+x-e.radius*m2px+1),(int)(h/2+y-e.radius*m2px+1), (int)(e.radius*2*m2px), (int)(e.radius*2*m2px));
                        //g.fillOval((int)(w/2- e.radius*m2px+1), (int)(h/2 - e.radius*m2px+1), (int)(e.radius*2*m2px), (int) (e.radius*2*m2px));
                        if(e.name != "" && e.name != null)
                                g.drawString(e.name, w/2, h/2);
                    break;
                    case Element.IS_VECTOR:
                        //draw vectors referenced to origin
                        
                        ((Graphics2D)g).setStroke(new BasicStroke(2.0f));
                        g.drawLine(w/2, h/2, w/2+x, h/2+y);

                        g.drawOval(w/2+x-1, h/2+y-1, 3, 3);
                        g.drawString(Integer.toString(i), w/2+x+10, h/2+y+10);

                        //draw names of each vector
                        if(e.name != "" && e.name != null && isTableEnabled)
                            g.drawString("["+i+"]: "+e.name, w-100, h*2/10+(i+2)*15);

                    break;
                }
                
            }
        }



        //at last, draw static elements
        for(int i=0;i<staticElems.size();i++)
        {
            Element e = (Element)staticElems.get(i);

            g.setColor(e.color);

            switch(e.type)
            {
                case Element.IS_CIRCLE:
                    ((Graphics2D)g).setStroke(new BasicStroke(1.0f));
                    g.drawOval((int)(w/2- e.radius*m2px+1), (int)(h/2 - e.radius*m2px+1), (int)(e.radius*2*m2px), (int) (e.radius*2*m2px));
                    if(e.name != "" && e.name != null)
                        g.drawString(e.name, w/2, (int)(h/2 - e.radius*m2px+1));
                break;
                case Element.IS_VECTOR:
                    //draw vectors referenced to origin
                    int x = (int)(e.x*m2px);
                    int y = -(int)(e.y*m2px);
                    
                    ((Graphics2D)g).setStroke(new BasicStroke(2.0f));
                    g.drawLine(w/2, h/2, w/2+x, h/2+y);

                    g.drawOval(w/2+x-1, h/2+y-1, 3, 3);
                    g.drawString(Integer.toString(i), w/2+x+10, h/2+y+10);

                    //draw names of each vector
                    if(e.name != "" && e.name != null && isTableEnabled)
                        g.drawString("["+i+"]: "+e.name, w-100, h*2/10+(i+2)*15);

                break;
            }


        }

        

    }
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        setBackground(new java.awt.Color(254, 254, 254));

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );
    }// </editor-fold>//GEN-END:initComponents


    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables

}

class Sector
{
    public int[] xPoints;
    public int[] yPoints;
    public Color color;
    public int index;

    public final static Color OCCUPIED = new Color(248,220,255);
    public final static Color FREE = Color.WHITE;


    public Sector(int[] xPoints, int[] yPoints,Color color, int index)
    {
        this.xPoints = xPoints;
        this.yPoints = yPoints;
        this.color = color;
        this.index = index;

    }

    public void setOccupied()
    {
        this.color = this.OCCUPIED;
    }

    public void setFree()
    {
        this.color = this.FREE;
    }


    public void draw(Graphics g, int offsetX, int offsetY)
    {
        int[] xx = xPoints.clone();
        int[] yy = yPoints.clone();
        for(int i= 0;i<xPoints.length;i++)
        {

            xx[i] += offsetX;
            yy[i] += offsetY;

        }
        g.setColor(color);
        g.fillPolygon(xx, yy, 3);
    }

}

class Element
{

    public static final int IS_VECTOR=0;
    public static final int IS_CIRCLE=1;
    public int type;

    public String name;
    public float radius;
    public float x;
    public float y;
    public boolean printName = false;
    public Color color;
    
    public Element(String name, int type, float radius, float x,float y, Color color)
    {
        this.type = type;
        this.name = name;
        this.radius = radius;
        this.x = x;
        this.y = y;
        this.color = color;

    }
}